"Covariance" = specified or MORE derived type
So upcasting to a more basic class in polymorphism is covariant.
object s = new string('a', 3);
But you couldn't do it for IEnumerables, even though it seemed safe. Well, now in .net 4 you can.
IList<string> stringList = new List<string>();
//will not compile in .net 1-3, but does in net 4
IEnumerable<object> objectList = stringList;
Trivia: since .net 1, arrays were covariant.
object[] data = new string[3];
data[0] = "s";
data[0] = 1; //no compiler error- just a runtime ArrayTypeMismatchException
Now IEnumerable<T> and IQueryable<T> are covariant
IList<Cat> cats = new List<Cat>();
//you can cast to IEnumerable (or IQueryable)
IEnumerable<Animal> pets = cats;
//but you cannot cast to the read-write classes
//IList<Animal> animals = cats; //compiler error
Covariant interfaces must be read-only (and not value types).
Contravariance = specified or LESS derived type
var cats = new List<Cat>();
//predicate is contravariant
cats.Find(HasFur); //private static bool HasFur(Animal animal)
//so is IComparable
cats.Sort(SortByName); //private static int SortByName(Animal x, Animal y)